<?php
/**
 * | 节程 [ 节程赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 *  | Copyright (c) 2020~2029 温州惊蛰网络科技有限公司 All rights reserved.
 * +----------------------------------------------------------------------
 *  | Licensed 节程并不是自由软件，未经许可不能去掉节程相关版权
 * +----------------------------------------------------------------------
 */


namespace app\index\service;

use app\index\model\Commodity;
use app\index\model\Configuration;
use app\index\model\Coupon;
use app\index\model\Order;
use app\index\model\SkuInventory;
use app\index\model\User;
use app\index\model\IntegralRecord;
use app\index\model\UserCash;
use app\utils\Addons;
use app\utils\RedisUtil;
use think\Exception;
use think\facade\Cache;
use think\facade\Db;

class IntegralService
{
    private $mid;
    public function __construct(){
        global $mid;
        $this->mid = $mid;
    }


    public function list(int $user_id, array $data, int $page = 1, int $size = 10) : array{
        $list = IntegralRecord::where('user_id',$user_id)
            ->where($this->where($data))
            ->where('status',1)
            ->order('create_time DESC')
            ->append(['type_text'])
            ->paginate(['page' => $page, 'list_rows' => $size]);
        return [HTTP_SUCCESS,$list];
    }


    private function where(array $data) : array{
        $where = ['mall_id' => $this->mid];
        !empty($data['start_date']) && $where[] = ['create_time','>=',$data['start_date']];
        !empty($data['end_date']) && $where[] = ['create_time','<=',$data['end_time']];
        return $where;
    }

    public function integral_address(array $select,int $order_id,int $user_id,int $mall_id) : void{
        $is_bool = Addons::check($mall_id,15);
        if (!$is_bool)return;
        $redis = new RedisUtil();
        foreach ($select AS $key => $value){
            $commodity = $redis->get(checkRedisKey('COMMODITY:'.$value['commodity_id']));
            if (empty($commodity))continue;
            $commodity = json_decode($commodity,true);
            if (empty($commodity['is_integral']))continue;
            if (empty($commodity['integral']))continue;
            $integral[] = [
                'user_id' => $user_id,
                'mall_id' => $mall_id,
                'order_id' => $order_id,
                'integral' => $value['count'] * $commodity['integral'],
                'commodity_id' => $value['commodity_id'],
                'sku_id' => empty($value['sku_id']) ? 0 : $value['sku_id'],
                'number' => $value['count'],
                'type' => 1,
                'status' => 0,
                'create_time' => date('Y-m-d H:i:s'),
                'update_time' => date('Y-m-d H:i:s')
            ];
        }
        if(!empty($integral))
            Db::name('integral_record')->insertAll($integral);
    }

    public function integral_judge(?string $commodity, int $user_id, float $total_price, ?array $coupon, int $mall_id) : array{
        $money = 0;
        $redis = new RedisUtil();
        $config = Configuration::where('type','integralBalance')->where('mall_id',$mall_id)->find();
        if ($config->configuration['is_open'] == 0)
            return [HTTP_SUCCESS,['money' => 0, 'integral' => 0]];
        $commodity = json_decode($commodity,true);
        if (empty($commodity))
            throw new Exception('商品不存在',HTTP_INVALID);
        $denomination = Coupon::where('id','IN',$coupon)->sum('denomination');
        empty($denomination) && $denomination = 0;
        $total_price = $total_price - $denomination;
        foreach ($commodity AS $key => $value) {
            $goods = $redis->get(checkRedisKey('COMMODITY:'.$value['commodityId']));
            $goods = json_decode($goods,true);
            if ($goods['integral_deduction'] == 0) continue;
            if ($goods['integral_maximum'] == 0) {
                if (!empty($value['attach']))
                    foreach ($value['attach'] AS $index => $item)$attach[] = $item;
                if (!empty($value['sku'])){
                    $sku[] = [$value['sku'],$value['commodityId']];
                    continue;
                }
                $commodity_id[] = $value['commodityId'];
            }else{
                $money += $goods['integral_maximum'];
            }
        }
        if (!empty($attach)){
            $attach_price = \think\facade\Db::name('attach_value')->where('id','IN',$attach)->field('id,price')->select();
            $price = [];
            foreach ($attach_price AS $key => $value)$price[$value['id']] = $value['price'];
            foreach ($attach AS $key => $value)$money += $price[$value];
        }
        if (!empty($commodity_id))
            foreach ($commodity_id AS $key => $value) $money += (new InventoryService($value))->getPrice();
//          $money += Commodity::where('id', 'IN', $commodity_id)->sum('sell_price');
        if (!empty($sku))
            foreach ($sku AS $key => $value) $money += (new InventoryService($value[1]))->getPrice($value[0]);
//            $money += SkuInventory::where('sku_id','IN',$sku)->sum('sell_price');
        $user_integral = UserCash::where('user_id',$user_id)->value('integral');
        $deduction = $config->configuration['deduction'] * 100;
        $amount = bcdiv($user_integral,$deduction == 0 ? 1 : $deduction,2);
        if ($amount < $money) $money = $amount;
        if ($total_price < $money) $money = $total_price;
        if ($money > 0) {
            $integral = bcmul($money, $deduction, 2);
            return [HTTP_SUCCESS, ['money' => $money, 'integral' => ceil($integral)]];
        }else{
            return [HTTP_SUCCESS, ['money' => 0, 'integral' => 0]];
        }
    }


    public function integral_calculation(array $commodityList, int $user_id,float $order_amount,float $deduction,int $order_id,int $mall_id) : array{
        $is_bool = Addons::check($mall_id,7);
        if (!$is_bool)return ['money' => 0,'discount_amount' => 0];
        $redis = new RedisUtil();
        $discount_amount = $attach_price = [];
        $money = $amount = $count = 0;
        $attach = array_column($commodityList,'attach');
        $attach = implode(',',$attach);
        $attach = \think\facade\Db::name('attach_value')
            ->field('id,price')
            ->where('id','IN',$attach)
            ->select();
        foreach ($attach AS $key => $value)
            $attach_price[$value['id']] = $value['price'];
        foreach ($commodityList AS $key => $value){
            $commodity = $redis->get(checkRedisKey('COMMODITY:'.$value['commodity']));
            $commodity = json_decode($commodity,true);
            if (!empty($commodity['integral_deduction'])){
                $count++;
                if ($commodity['integral_maximum'] == 0) {
                    if (!empty($value['attach'])) {
                        $sum = 0;
                        $in_array =  explode(',',$value['attach']);
                        foreach ($attach_price AS $index => $item) if (in_array($index,$in_array)) $sum += $item;
                        $amount = $value['price'] + $sum;
                    }else {
                        $amount = $value['price'];
                    }
                }else{
                    $amount =$commodity['integral_maximum'];
                }
                $money += $amount;
                $discount_amount[] = ['id' => $value['commodity'],'sku' => $value['sku'] ,'group' => $value['group'],'amount' => $amount,'price' => $value['price']];
            }
        }
        if($money == 0)return ['money' => 0,'discount_amount' => []];
        foreach($discount_amount AS $key => $value){
            $proportion = bcdiv($value['amount'],$money == 0 ? 1: $money,4);
            $discount_amount[$key]['proportion'] = $proportion;
        }
        $user_integral = UserCash::where('user_id',$user_id)->value('integral');
        $amount = bcdiv($user_integral,$deduction == 0 ? 1 : $deduction,2);
        $discount = Order::where('id',$order_id)->value('discount');
        empty($discount) && $discount = 0;
        $order_amount = $order_amount - $discount;
        $is_bool = false;
        if ($amount < $money) {
            $money = $amount;
            $is_bool = true;
        }
        if ($order_amount < $money) {
            $money = $order_amount;
            $is_bool = true;
        }
        if ($is_bool){
            $amount = 0;
            foreach ($discount_amount AS $key => $value) {
                $float = bcmul($value['proportion'], $money, 2);
                $discount_amount[$key]['amount'] = $float;
                $amount += $float;
            }
            if($amount != $money){
                $amount = bcsub($money , $amount,2);
                $discount_amount[$key]['amount'] += $amount;
            }
        }
        return ['money' => $money,'discount_amount' => $discount_amount];
    }


    public function integral_deduction(array $discount, int $user_id,float $deduction,int $order_id,int $mall_id) : void{
        $is_bool = Addons::check($mall_id,7);
        if (!$is_bool)return;
            $integral = bcmul($discount['money'],$deduction,2);
        Db::name('user_cash')
            ->where('user_id',(string)$user_id)
            ->dec('integral',$integral)
            ->inc('integral_withdraw',$integral)
            ->update(['update_time' => now()]);
        Db::name('order')
            ->where('id',$order_id)
            ->inc('discount_amount',$discount['money'])
            ->update(['update_time' => now()]);
        if (!empty($discount['discount_amount'])) {
            $sql = '';
            foreach ($discount['discount_amount'] AS $key => $value){
                if (empty($value['sku']))
                    $sql .= "when (`commodity_id` = {$value['id']} AND `group` = {$value['group']}) then {$value['amount']} ";
                else
                    $sql .= "when (`commodity_id` = {$value['id']} AND `group` = {$value['group']} AND `sku_id` = {$value['sku']}) then {$value['amount']} ";
            }
            if (!empty($sql))
                $sql = 'update `jiecheng_order_commodity` set `discount_amount` = case '.$sql.'else 0 end where `order_id` = '.$order_id;
            Db::query($sql);
        }
        IntegralRecord::create([
            'integral' => $integral,
            'mall_id' => $mall_id,
            'user_id' => $user_id,
            'order_id' => $order_id,
            'sku_id' => 0,
            'commodity_id' => 0,
            'number' => 0,
            'type' => 2,
            'status' => 1,
            'create_time' => now(),
            'update_time' => now()
        ]);
    }


    public function share_integral(int $user_id,int $id) : array{
        if (empty(Db::name('visit')->where('user_id',$id)->count())) {
            $response = request();
            $ip = $response->ip();
            $url = $response->pathinfo();
            $mall_id = $response->header('mid');
            $visit = ['ip' => $ip,'url' => 'index/'.$url,'create_time' => now(),'agent_id' => $user_id,'user_id' => $id,'merchant_id' => $user->merchant_id ?? 0,'mall_id' => $mall_id,'mode' => 'index/'.$_SERVER['REQUEST_METHOD'], 'is_fission' => 1];
            Cache::set($id.'visit',['id' => $id,'agent_id' => $user_id],86400);
            Db::name('visit')->insert($visit);
        }
        $is_bool = Addons::check($this->mid,6);
        if (!$is_bool)return [HTTP_SUCCESS,' 成功'];
        if ($user_id == $id)
            return [HTTP_SUCCESS,' 成功'];
        $user = Db::name('user')
            ->field('id,merchant_id,create_time,update_time')
            ->where('id',$user_id)
            ->find();
        if (empty($user))
            throw new Exception('用户不存在',HTTP_INVALID);
        $count = Db::name('integral_record')
            ->where('user_id',$id)
            ->where('commodity_id',$user_id)
            ->count();
        if ($count > 1)
            return [HTTP_SUCCESS,' 成 功'];
        $time = strtotime($user['update_time']) - strtotime($user['create_time']);
        $count = Db::name('integral_record')
            ->where('commodity_id',$user_id)
            ->count();
        $is_bool = $time < 86400 && $count == 0;
        $user = User::find($id);
        if (empty($user))
            throw new Exception('用户不存在',HTTP_INVALID);
        $count = Db::name('integral_record')
            ->where('user_id',$user_id)
            ->whereDay('create_time','today')
            ->where('type',3)
            ->count();
        $config = Db::name('configuration')
            ->where('type','integralBalance')
            ->value('configuration');
        $config = json_decode($config);
        if ($count >= $config->daily_limit)
            return [HTTP_SUCCESS,'成 功'];
        Db::name('user_cash')
            ->where('user_id',$user_id)
            ->inc('integral',$is_bool ? $config->share->new : $config->share->old)
            ->update(['update_time' => now()]);
        Db::name('integral_record')
            ->insert([
                'user_id' => $user_id,
                'order_id' => 0 ,
                'commodity_id' => $id,
                'sku_id' => 0,
                'number' => 0,
                'type' => 3,
                'status' => 1,
                'integral' => $is_bool ? $config->share->new : $config->share->old,
                'create_time' => date('Y-m-d H:i:s'),
                'update_time' => date('Y-m-d H:i:s')
            ]);
        return [HTTP_SUCCESS,'成功'];
    }
}